#include "camembert.h"

void drawTexCamembert (Point c,double R, int nbcoup,
		       double SALPHA,double SBETA,double interBeta,
		       char* file_top,char* file_bottom)
{
  chooseColor(1.,1.,1.);
/* sauvegarde de la matrice */
  /* pour la mouse */

  glPushMatrix();
/* changement du repère */
  /* on commence par mettre le centre en 0,0,0 */
  glTranslatef(c.x,c.y,c.z);

  glRotatef(SALPHA,0,0,1);
  /* en effet si SBETA vaut 90, on bouge pas */
  /* de plus notre angle est orienté a l'envers =) */
  glRotatef(360-(SBETA-90.),0,1,0);
  
  /* cette rotation place le centre de l'image au top */
  /* de la sphere */
  /* glRotatef(90,0,1,0); */

  /* le centre est en 0,0,0, donc  */
  /* les points sont considérés comme des vecteurs */
  /* (en particulier on ajoute plus les coordonnées du  */
  /* centre) */
  double x,y,z;
  double alpha=0.;
/* le remplissage se fait de bas en haut */
  double beta=-90.;
  double r;
  Point p1,p2,p3,p4;

  double pasAlpha=360./(double)nbcoup;
  double pasBeta=180./(double)nbcoup;
  int nombreCercles=0;

  int i=0,j=0;
  double aPartirDe=0.;
  /* on compte le nombre de cercle qu'on va tracer */
  while (beta<-interBeta)
      beta+=pasBeta;
  /* beta commencera a partir de la */
  aPartirDe=beta;
  while(beta<interBeta) {
      beta+=pasBeta;
      nombreCercles++;
  }
  beta=aPartirDe;
/* puis on remet beta à son point de départ réel */

/* la matrice n'a que nombreCercle lignes, */
/* car la sphere aura nombreCercle étages */
  Point** matrice=newMatricePoint_noSquare(nombreCercles,nbcoup+1);

  for (i=0;i<nombreCercles;i++)
    {
      /* le rayon du sous cercle */
      r=R*cos(rad(beta));
      /* le sous cercle qu'on trace */
      z=sin(rad(beta))*R;

      
      /* j fait bien tout le tour en revanche */
      for (j=0;j<nbcoup+1;j++)
	{
	  /* cercle des x par rapport aux y */
	  x=cos(rad(alpha))*r;
	  y=sin(rad(alpha))*r;
	  alpha+=pasAlpha;

	  matrice[i][j]=pt(x,y,z);
	  /* si ce n'est pas le premier tour, on dessine des quad */
	  if (i!=0)
	    {
	      if (j>0)
		{
		  glBegin(GL_QUADS);
		  /* on traite 2 points d'un étage inferieur */

		  p1=matrice[i-1][j];
		  glTexCoord2d(((double)i-1.)/(double)((nombreCercles-1.)),(double)j/(double)(nbcoup+1.));
		  glVertex3d(p1.x,p1.y,p1.z);

		  p2=matrice[i-1][j-1];
		  glTexCoord2d(((double)i-1.)/(double)(nombreCercles-1.),((double)j-1.)/(double)(nbcoup+1.));
		  glVertex3d(p2.x,p2.y,p2.z);
		  /* puis 2 point de l'étage superieur */
		  p3=matrice[i][j-1];
		  glTexCoord2d((double)i/(double)(nombreCercles-1.),((double)j-1.)/(double)(nbcoup+1.));
		  glVertex3d(p3.x,p3.y,p3.z);

		  p4=matrice[i][j];
		  glTexCoord2d((double)i/(double)(nombreCercles-1.),(double)j/(double)(nbcoup+1.));
		  glVertex3d(p4.x,p4.y,p4.z);
		  glEnd();
		}
	    }
	}
      alpha=0.;
      beta+=pasBeta;
    }

  /* map du bottom */
  mapDisque (nbcoup,pasAlpha,matrice[0], file_bottom);
  /* map du top */
  mapDisque (nbcoup,pasAlpha,matrice[nombreCercles-1], file_top);

  libererMatricePoint(matrice,nombreCercles);


  /* on restaure l'ancienne matrice */
  glPopMatrix();
  return;
}


/* pareil que drawTexCamembert, mais sans commentaires */
/* et avec la texture répété le nombre de fois désiré */
void drawTexRepeatCamembert (Point c,double R, int nbcoup,
			     double SALPHA,double SBETA,
			     double interBeta,int maxRepeat,
			     char* file_top,char* file_bottom)
{
  chooseColor(1.,1.,1.);
  glPushMatrix();
  glTranslatef(c.x,c.y,c.z);
  glRotatef(SALPHA,0,0,1);
  glRotatef(360-(SBETA-90.),0,1,0);
  double x,y,z;
  double alpha=0.;
  double beta=-90.;
  double r;
  Point p1,p2,p3,p4;
  /* esquive de la division par 0 */
  if (maxRepeat==0)
    maxRepeat=1;
  int repeat=nbcoup/maxRepeat;
  double pasAlpha=360./((double)nbcoup);
  double pasBeta=180./((double)nbcoup);
  int nombreCercles=0;

  int i=0,j=0;
  double aPartirDe=0.;
  while (beta<-interBeta)
      beta+=pasBeta;
  aPartirDe=beta;
  while(beta<interBeta) {
      beta+=pasBeta;
      nombreCercles++;
  }

/* si il n'y a aucun cercle qui entre dans l'intervalle */
/* on sort, sans oublier de depiler la matrice */
  if (nombreCercles==0) {
    glPopMatrix();
    return;
  }

  beta=aPartirDe;
  Point** matrice=newMatricePoint_noSquare(nombreCercles,nbcoup+1);
  for (i=0;i<nombreCercles;i++)
    {
      r=R*cos(rad(beta));
      z=sin(rad(beta))*R;
      for (j=0;j<nbcoup+1;j++)
	{
	  x=cos(rad(alpha))*r;
	  y=sin(rad(alpha))*r;
	  alpha+=pasAlpha;
	  matrice[i][j]=pt(x,y,z);
	  if (i!=0)
	    {
	      if (j>0)
		{
		  glBegin(GL_QUADS);
		  p1=matrice[i-1][j];
		  glTexCoord2d(((double)i-1.)/(double)((nombreCercles-1.)),(double)j/(double)(repeat));
		  glVertex3d(p1.x,p1.y,p1.z);

		  p2=matrice[i-1][j-1];
		  glTexCoord2d(((double)i-1.)/(double)(nombreCercles-1.),((double)j-1.)/(double)(repeat)); 
		  glVertex3d(p2.x,p2.y,p2.z);
		  p3=matrice[i][j-1];
		  glTexCoord2d((double)i/(double)(nombreCercles-1.),((double)j-1.)/(double)(repeat));
		  glVertex3d(p3.x,p3.y,p3.z);

		  p4=matrice[i][j];
		  glTexCoord2d((double)i/(double)(nombreCercles-1.),(double)j/(double)(repeat));
		  glVertex3d(p4.x,p4.y,p4.z);
		  glEnd();
		}
	    }
	}
      alpha=0.;
      beta+=pasBeta;
    }

  /* map du bottom */
  mapDisque (nbcoup,pasAlpha,matrice[0], file_bottom);
  /* map du top */
  mapDisque (nbcoup,pasAlpha,matrice[nombreCercles-1], file_top);

  libererMatricePoint(matrice,nombreCercles-1);
  glPopMatrix();
  return;
}

void mapDisque (int nbcoup,double pasAlpha,Point* etage, char* filename)
{

  GLuint id=0; /* pour les texels disques */
  int j; /* compteur */
  Point p1,p2,p3,p4; /* place les points des quads */
  /* on draw les disques maintenant: premier étage et dernier étage */
  id=load_secure_texel(id,filename);

  double alpha=0.; /* compteur */

/* le cas ou la face a moins de 4 sommets n'est pas géré */
  if (nbcoup<4)
    return;

  for (j=0;j<(nbcoup+1)/2;j++)
    {
      glBegin(GL_QUADS);
      p1=etage[j];
      glTexCoord2d((cos(rad(alpha))+1.)/2.,(sin(rad(alpha))+1.)/2.);
      glVertex3d(p1.x,p1.y,p1.z);

      p2=etage[j+1];
      glTexCoord2d((cos(rad(alpha+pasAlpha))+1.)/2.,(sin(rad(alpha+pasAlpha))+1.)/2.);
      glVertex3d(p2.x,p2.y,p2.z);

      p4=etage[nbcoup-j];
      glTexCoord2d((cos(rad(360.-(alpha+pasAlpha)))+1.)/2.,(sin(rad(360.-(alpha+pasAlpha)))+1.)/2.);
      glVertex3d(p4.x,p4.y,p4.z);

      p3=etage[nbcoup+1-j];
      glTexCoord2d((cos(rad(360.-alpha))+1.)/2.,(sin(rad(360.-alpha))+1.)/2.); /* inversion */
      glVertex3d(p3.x,p3.y,p3.z);

      glEnd();

      alpha+=pasAlpha;
    }

}
